/*
 * CopyRight(C) Kenbin
 */

#include <string.h>
#include <stdlib.h>
#include "lws_recog.h"
#include "lws_basicseg.h"

LWS::CBasicSeg::CBasicSeg(CTrieDict *trie_dict) : m_trie_dict(trie_dict)
{
}

void LWS::CBasicSeg::Segment(char *text, CWordGraph *word_graph, bool is_atom_recog)
{
    if(text == NULL) {
	return;
    }

    m_atom_ptrs.resize(0);
    m_atom_tags.resize(0);
    m_atom_trieidxs.resize(0);

    if(is_atom_recog) {
	recog_atom_segment(text);
    } else {
	simple_atom_segment(text);
    }
    m_atom_ptrs.push_back(text + strlen(text));

    word_graph->Init(m_atom_ptrs.size());

    /* add atom_segment result to wordgraph */
    for(unsigned i = 0; i < m_atom_ptrs.size()-1; i ++) {
	string atom(m_atom_ptrs[i], m_atom_ptrs[i+1]);
	int atom_trieidx = m_trie_dict->CHARIndex(atom);

	m_atom_trieidxs.push_back(atom_trieidx);

	word_graph->AddWord(i, i, m_trie_dict->WordId(atom_trieidx), 
		m_trie_dict->WordProb(atom_trieidx));
    }

    /* add complete_segment result to wordgraph */
    for(unsigned i = 0; i < m_atom_trieidxs.size(); i ++) {
	if(m_atom_trieidxs[i] < 0) {
	    continue;
	}

	int c = i + 1;
	int s = m_atom_trieidxs[i];
	int t = abs(m_trie_dict->Base(s)) + m_atom_trieidxs[c];

	while(m_trie_dict->Check(t) == s) {
	    if(m_trie_dict->Base(t) < 0) {
		string word(m_atom_ptrs[i], m_atom_ptrs[c+1]);
		word_graph->AddWord(i, c, m_trie_dict->WordId(t), m_trie_dict->WordProb(t));
	    }

	    s = t;
	    if(++ c < m_atom_trieidxs.size()) {
		if(m_atom_trieidxs[i] < 0) {
		    break;
		} else {
		    t = abs(m_trie_dict->Base(s)) + m_atom_trieidxs[c];
		}
	    } else {
		break;
	    }
	}
    }

    /* recog atom ASCII letter to string */
    int end = 0, flag = 0;
    for(int i = word_graph->m_word_graph.size()-1; i > 0; i --) {
	if(word_graph->m_word_graph[i].size() == 1) {
	    char cur = *m_atom_ptrs[i-1];
	    char nxt = *(m_atom_ptrs[i-1]+1);

	    if(cur >= 'A' && cur <= 'Z' || cur >= 'a' && cur <= 'z') {
		if(flag == 0) {
		    end = i-1;
		    flag = 1;
		}
	    } else if(end > i) {
		word_graph->AddWord(i, end, UNKNOWN, 0);
		end = flag = 0;
	    } else {
		end = flag = 0;
	    }
	} else {
	    if(end > i) {
		word_graph->AddWord(i, end, UNKNOWN, 0);
	    }

	    int min_prenode = word_graph->m_word_graph.size();
	    for(int j = 0; j < word_graph->m_word_graph.size(); j ++) {
		if(word_graph->m_word_graph[i][j].pre_node < min_prenode) {
		    min_prenode = word_graph->m_word_graph[i][j].pre_node;
		}
	    }

	    i = min_prenode + 1;
	    end = flag = 0;
	}
    }

    if(end > 0) {
	word_graph->AddWord(0, end, UNKNOWN, 0);
    }
}

void LWS::CBasicSeg::recog_atom_segment(char *text)
{
    /* status tag
       0 - GBK letter
       1 - GBK number
       2 - GBK Hanzi
       3 - GBK symbol
       4 - ASCII letter
       5 - ASCII number
       6 - ASCII symbol
       */

    int prev_status = 0; /* start */
    int text_len = strlen(text);

    unsigned P = 0;
    while(P < text_len) {
	if(prev_status == 0) {
	    if(text[P] == (char)0xA3 && (text[P+1] >= (char)0xC1 && text[P+1] <= (char)0xDA
		|| text[P+1] >= (char)0xE1 && text[P+1] <= (char)0xFA)) { 
		/* GBK letter */
		if(P == 0) { /* start */
		    m_atom_ptrs.push_back(text+P);
		    m_atom_tags.push_back(1);
		}
		P += 2;
	    } else if(text[P] == (char)0xA3 && (text[P+1] >= (char)0xB1 && text[P+1] <= (char)0xB9)) {
		/* GBK number */
		prev_status = 1;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P += 2;
	    } else if(text[P] >= (char)0xB0 && text[P] <= (char)0xF7) {
		/* GBK Hanzi */
		prev_status = 2;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P += 2;
	    } else if(text[P] < 0) {
		/* GBK symbol */
		prev_status = 3;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(0);
		P += 2;
	    } else if(text[P] >= 'A' && text[P] <= 'Z' || text[P] >= 'a' && text[P] <= 'z') {
		/* ASCII letter */
		prev_status = 4;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P ++;
	    } else if(text[P] >= '0' && text[P] <= '9') {
		/* ASCII number */
		prev_status = 5;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P ++;
	    } else {
		/* ASCII symbol */
		prev_status = 6;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(0);
		P ++;
	    }
	} else if(prev_status == 1) {
	    if(text[P] == (char)0xA3 && (text[P+1] >= (char)0xC1 && text[P+1] <= (char)0xDA
		|| text[P+1] >= (char)0xE1 && text[P+1] <= (char)0xFA)) { 
		/* GBK letter */
		prev_status = 0;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P += 2;
	    } else if(text[P] == (char)0xA3 && (text[P+1] >= (char)0xB1 && text[P+1] <= (char)0xB9)) {
		/* GBK number */
		P += 2;
	    } else if(text[P] >= (char)0xB0 && text[P] <= (char)0xF7) {
		/* GBK Hanzi */
		prev_status = 2;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P += 2;
	    } else if(text[P] < 0) {
		/* GBK symbol */
		prev_status = 3;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(0);
		P += 2;
	    } else if(text[P] >= 'A' && text[P] <= 'Z' || text[P] >= 'a' && text[P] <= 'z') {
		/* ASCII letter */
		prev_status = 4;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P ++;
	    } else if(text[P] >= '0' && text[P] <= '9') {
		/* ASCII number */
		prev_status = 5;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P ++;
	    } else {
		/* ASCII symbol */
		prev_status = 6;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(0);
		P ++;
	    }
	} else if(prev_status == 2) {
	    if(text[P] == (char)0xA3 && (text[P+1] >= (char)0xC1 && text[P+1] <= (char)0xDA
		|| text[P+1] >= (char)0xE1 && text[P+1] <= (char)0xFA)) { 
		/* GBK letter */
		prev_status = 0;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P += 2;
	    } else if(text[P] == (char)0xA3 && (text[P+1] >= (char)0xB1 && text[P+1] <= (char)0xB9)) {
		/* GBK number */
		prev_status = 1;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P += 2;
	    } else if(text[P] >= (char)0xB0 && text[P] <= (char)0xF7) {
		/* GBK Hanzi */
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P += 2;
	    } else if(text[P] < 0) {
		/* GBK symbol */
		prev_status = 3;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(0);
		P += 2;
	    } else if(text[P] >= 'A' && text[P] <= 'Z' || text[P] >= 'a' && text[P] <= 'z') {
		/* ASCII letter */
		prev_status = 4;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P ++;
	    } else if(text[P] >= '0' && text[P] <= '9') {
		/* ASCII number */
		prev_status = 5;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P ++;
	    } else {
		/* ASCII symbol */
		prev_status = 6;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(0);
		P ++;
	    }
	} else if(prev_status == 3) {
	    if(text[P] == (char)0xA3 && (text[P+1] >= (char)0xC1 && text[P+1] <= (char)0xDA
		|| text[P+1] >= (char)0xE1 && text[P+1] <= (char)0xFA)) { 
		/* GBK letter */
		prev_status = 0;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P += 2;
	    } else if(text[P] == (char)0xA3 && (text[P+1] >= (char)0xB1 && text[P+1] <= (char)0xB9)) {
		/* GBK number */
		prev_status = 1;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P += 2;
	    } else if(text[P] >= (char)0xB0 && text[P] <= (char)0xF7) {
		/* GBK Hanzi */
		prev_status = 2;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P += 2;
	    } else if(text[P] < 0) {
		/* GBK symbol */
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(0);
		P += 2;
	    } else if(text[P] >= 'A' && text[P] <= 'Z' || text[P] >= 'a' && text[P] <= 'z') {
		/* ASCII letter */
		prev_status = 4;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P ++;
	    } else if(text[P] >= '0' && text[P] <= '9') {
		/* ASCII number */
		prev_status = 5;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P ++;
	    } else {
		/* ASCII symbol */
		prev_status = 6;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(0);
		P ++;
	    }
	} else if(prev_status == 4) {
	    if(text[P] == (char)0xA3 && (text[P+1] >= (char)0xC1 && text[P+1] <= (char)0xDA
		|| text[P+1] >= (char)0xE1 && text[P+1] <= (char)0xFA)) { 
		/* GBK letter */
		prev_status = 0;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P += 2;
	    } else if(text[P] == (char)0xA3 && (text[P+1] >= (char)0xB1 && text[P+1] <= (char)0xB9)) {
		/* GBK number */
		prev_status = 1;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P += 2;
	    } else if(text[P] >= (char)0xB0 && text[P] <= (char)0xF7) {
		/* GBK Hanzi */
		prev_status = 2;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P += 2;
	    } else if(text[P] < 0) {
		/* GBK symbol */
		prev_status = 3;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(0);
		P += 2;
	    } else if(text[P] >= 'A' && text[P] <= 'Z' || text[P] >= 'a' && text[P] <= 'z') {
		/* ASCII letter */
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P ++;
	    } else if(text[P] >= '0' && text[P] <= '9') {
		/* ASCII number */
		prev_status = 5;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P ++;
	    } else {
		/* ASCII symbol */
		prev_status = 6;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(0);
		P ++;
	    }
	} else if(prev_status == 5) {
	    if(text[P] == (char)0xA3 && (text[P+1] >= (char)0xC1 && text[P+1] <= (char)0xDA
		|| text[P+1] >= (char)0xE1 && text[P+1] <= (char)0xFA)) { 
		/* GBK letter */
		prev_status = 0;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P += 2;
	    } else if(text[P] == (char)0xA3 && (text[P+1] >= (char)0xB1 && text[P+1] <= (char)0xB9)) {
		/* GBK number */
		prev_status = 1;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P += 2;
	    } else if(text[P] >= (char)0xB0 && text[P] <= (char)0xF7) {
		/* GBK Hanzi */
		prev_status = 2;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P += 2;
	    } else if(text[P] < 0) {
		/* GBK symbol */
		prev_status = 3;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(0);
		P += 2;
	    } else if(text[P] >= 'A' && text[P] <= 'Z' || text[P] >= 'a' && text[P] <= 'z') {
		/* ASCII letter */
		prev_status = 4;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P ++;
	    } else if(text[P] >= '0' && text[P] <= '9') {
		/* ASCII number */
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P ++;
	    } else {
		/* ASCII symbol */
		prev_status = 6;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(0);
		P ++;
	    }
	} else if(prev_status == 6) {
	    if(text[P] == (char)0xA3 && (text[P+1] >= (char)0xC1 && text[P+1] <= (char)0xDA
		|| text[P+1] >= (char)0xE1 && text[P+1] <= (char)0xFA)) { 
		/* GBK letter */
		prev_status = 0;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P += 2;
	    } else if(text[P] == (char)0xA3 && (text[P+1] >= (char)0xB1 && text[P+1] <= (char)0xB9)) {
		/* GBK number */
		prev_status = 1;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P += 2;
	    } else if(text[P] >= (char)0xB0 && text[P] <= (char)0xF7) {
		/* GBK Hanzi */
		prev_status = 2;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P += 2;
	    } else if(text[P] < 0) {
		/* GBK symbol */
		prev_status = 3;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(0);
		P += 2;
	    } else if(text[P] >= 'A' && text[P] <= 'Z' || text[P] >= 'a' && text[P] <= 'z') {
		/* ASCII letter */
		prev_status = 4;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P ++;
	    } else if(text[P] >= '0' && text[P] <= '9') {
		/* ASCII number */
		prev_status = 5;
		m_atom_ptrs.push_back(text+P);
		m_atom_tags.push_back(1);
		P ++;
	    } else {
		/* ASCII symbol */
		P ++;
	    }
	}
    }
}

void LWS::CBasicSeg::simple_atom_segment(char *text)
{
    int text_len = strlen(text);
    for(int i = 0; i < text_len; i ++) {
	if(text[i] < 0) { /* maybe GB2312, GBK */
	    m_atom_ptrs.push_back(text+i);
	    m_atom_tags.push_back(1);
	    i ++;
	} else {
	    m_atom_ptrs.push_back(text+i);
	    m_atom_tags.push_back(1);
	}
    }
}
